from django.shortcuts import render

# Create your views here.
#  验证app,专门用于验证,独立于users

import logging   # 导入日志模块 python自带
import json
import string
import random


from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse,JsonResponse
from django.views import View
from django_redis import get_redis_connection   # redis模块

from utils.captcha.captcha import captcha   # 生成图片验证码的实例,
from . import constants   # 验证码图片过期时间
from users.models import Users

from utils.res_code import Code,error_map
from . import forms
from utils.yuntongxun.sms import CCP

# 日志器实例
from .forms import CheckImageForm

logger =logging.getLogger('django')
# 1.创建视图    图片验证码实现
def image_code_view(request):
    """
    define image verification view    定义图片验证视图
    /image_code/<uuid:image_code_id>   接口的url路径定义
    """

    text, image = captcha.generate_captcha()
    # 4.建立redis,并且将图片验证码保存到redis
    request.session['image_code'] = text
    request.session.set_expiry(constants.IMAGE_CODE_EXPIRES)
    logger.info('Image code:{}'.format(text))  # 后台显示日志信息--验证码文本
    return HttpResponse(content=image, content_type='image/jpg')


from users.models import Users
from utils.json_fun import json_response

#校验用户名
def check_username_view(request, username):
    # 去数据库查询数据,然后返回就好了
    data = {
        'errno': '0',
        'errmsg': 'ok',
        'data':{
            'username': username,
            'count': Users.objects.filter(username=username).count()
        }

    }

    return json_response(data=data)


def check_mobile_view(request, mobile):
    """
    校验手机号是否存在
    url:/moblie/(?P<moblie>1[3-9]\d{9})/
    :param request:
    :param username:
    :return:
    """
    data = {
        'mobile': mobile,
        'count': Users.objects.filter(mobile=mobile).count()
    }

    return json_response(data=data)


class SmsCodeView(View):
    """
    发送短信验证码
    POST /sms_codes/
    """
    def post(self, request):
        # 1.校验参数

        form = CheckImageForm(request.POST, request=request)
        if form.is_valid():
            # 2.获取手机
            mobile = form.cleaned_data.get('mobile')
            # 3.生成手机验证码
            sms_code = ''.join([random.choice('0123456789') for _ in range(constants.SMS_CODE_LENGTH)])
            # 4.发送手机验证码
            ccp = CCP()
            try:
                res = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRES], "1")
                if res == 0:
                    logger.info('发送短信验证码[正常][mobile: %s sms_code: %s]' % (mobile, sms_code))
                else:
                    logger.error('发送短信验证码[失败][moblie: %s sms_code: %s]' % (mobile, sms_code))
                    return json_response(errno=Code.SMSFAIL, errmsg=error_map[Code.SMSFAIL])
            except Exception as e:
                logger.error('发送短信验证码[异常][mobile: %s message: %s]' % (mobile, e))
                return json_response(errno=Code.SMSERROR, errmsg=error_map[Code.SMSERROR])


            # 5.保存到redis数据库
            # 创建短信验证码发送记录
            sms_flag_key = 'sms_flag_{}'.format(mobile)
            # 创建短信验证码内容记录
            sms_text_key = 'sms_text_{}'.format(mobile)

            redis_conn = get_redis_connection(alias='verify_codes')
            pl = redis_conn.pipeline()

            try:
                pl.setex(sms_flag_key, constants.SMS_CODE_INTERVAL, 1)
                pl.setex(sms_text_key, constants.SMS_CODE_EXPIRES*60, sms_code)
                # 让管道通知redis执行命令
                pl.execute()
                return json_response(errmsg="短信验证码发送成功！")
            except Exception as e:
                logger.error('redis 执行异常：{}'.format(e))

                return json_response(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])

        else:
            # 将表单的报错信息进行拼接
            err_msg_list = []
            for item in form.errors.get_json_data().values():
                err_msg_list.append(item[0].get('message'))
                # print(item[0].get('message'))   # for test
            err_msg_str = '/'.join(err_msg_list)  # 拼接错误信息为一个字符串

            return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)
# 1.创建视图    判断用户是否注册

# class CheckUsernameView(View):
#     """
#     check whether the user exists   判断用户是否存在
#      GET usernames/(?P<username>\w{5,20})/  请求方法,url
#     """
#     # 2.校验参数
#     def get(self, request, username):
#         # user = Users.objects.filter(username=username)
#         # # 4.返回校验的结果
#         # if not user:                                         # 此方法前端不能看到,不适用
#         #     return HttpResponse('可以注册')
#         # else:
#         #     return HttpResponse('不能注册')
#
#         # 如果用get方法,当数据不存在就会报错,就要捕获异常:
#
#         # try:
#         #     user = Users.objects.get(username=username)
#         #     data = {
#         #         'username': username,
#         #
#         #         'count': user,  # 1 或者0
#         #     }
#         #
#         # except ObjectDoesNotExist:
#         #     return to_json_data(errno=Code.NODATA,errmsg=error_map[Code.NODATA])
#         # else:
#         #     return to_json_data(data=data)
#
#
#         count = Users.objects.filter(username=username).count()  # 数据统计
#         data ={
#             'username':username,
#             #'count': True if count else False   # 存在就是True,否则为0
#             'count':count,  # 1 或者0
#         }
#         #return JsonResponse(data=data)  # 返回json数据给前端判断
#         return to_json_data(data=data)
#
# # 判断手机号码是否存在
# class CheckMobileView(View):
#     """
#     Check whether the mobile exists
#     GET mobiles/(?P<mobile>1[3-9]\d{9})/  请求方法 url
#     """
#     def get(self,request,mobile):
#         data = {
#             'mobile': mobile,
#             'count': Users.objects.filter(mobile=mobile).count()
#         }
#         return to_json_data(data=data)
#
# # 1 创建一个类  发送短信验证码          短信验证码校验
# class SmsCodesView(View):
#     """
#     send mobile sms code
#     POST  /sms_codes/
#     """
#     # 2.获取前端ajax请求的json格式数据
#     def post(self,request):
#         json_data = request.body                #  获取前端的json数据
#         if not json_data:
#             return to_json_data(errno=Code.PARAMERR,errmsg="参数为空,请重新输入!")
#         dict_data = json.loads(json_data.decode("utf8"))     #  把json数据转换为后端字典格式的数据
#     # 3.校验参数
#     #     mobile = dict_data.get('mobile')       # 此方法校验3个参数会有多层嵌套的if语句,过于繁琐
#     #     text = dict_data.get('text')
#     #     image_code_id = dict_data.get('image_code_id')
#
#     # 利用form表单进行校验   sms 短信验证码的缩写
#         form = forms.CheckImgCodeForm(data=dict_data)  # 定义表单,并传入数据
#         if form.is_valid():              # 如果表单校验成功/存在
#             # 4.发送短信验证码
#             mobile = form.cleaned_data.get('mobile')  # 获取手机号
#             sms_num = ''.join([random.choice(string.digits) for _ in range(6)]) # 从0-9中随机选择6次,构成验证码
#         #   sms_num = ''.join([random.choice('0123456789') for _ in range(6)]) #  _ 占位符,不占用内存,也可以用任意变量,
#
#             # 5.保存短信验证码到redis中
#             redis_con = get_redis_connection(alias='verify_codes')
#             sms_flag_fmt = "sms_flag_{}".format(mobile).encode('utf8')  # 创建钥匙
#             sms_text_fmt = "sms_{}".format(mobile).encode('utf8')
#             p1 = redis_con.pipeline()  # 创建一个管道,同时执行下面两条命令
#             try:
#                 p1.setex(sms_flag_fmt,constants.SEND_SMS_CODE_INTERVAL,1)  # 设置钥匙/记录过期时间60秒, ()内name,time,value   value不能为0获取false,其他度可以
#                 p1.setex(sms_text_fmt,constants.SMS_CODE_REDIS_EXPIRES,sms_num)  #设置验证码的过期时间,本身是真实的,value可以为sms_num
#                 p1.execute()
#             except Exception as e :
#                 logger.debug("redis执行出现异常:{}".format(e))
#                 return to_json_data(errno=Code.UNKOWNERR,errmsg=error_map[Code.UNKOWNERR])
#
#             # 发送短信验证码  假定发送成功 (实际开发需要付费,用下面的代码)
#             logger.info("发送验证码短信[正常][ mobile: %s sms_code: %s]" % (mobile, sms_num))
#             return to_json_data(errno=Code.OK, errmsg="短信验证码发送成功")
#             # 6 云通讯发送短信验证码   需要付费
#             # try:
#             #   result = CCP().send_template_sms(mobile,
#             #                                 [sms_num, constants.SMS_CODE_YUNTX_EXPIRES],
#             #                                 constants.SMS_CODE_TEMP_ID)
#             # except Exception as e:
#             #     logger.error("发送验证码短信[异常][ mobile: %s, message: %s ]" % (mobile, e))
#             #     return to_json_data(errno=Code.SMSERROR, errmsg=error_map[Code.SMSERROR])
#             # else:
#             #     if result == 0:
#             #         logger.info("发送验证码短信[正常][ mobile: %s sms_code: %s]" % (mobile, sms_num))
#             #         return to_json_data(errno=Code.OK, errmsg="短信验证码发送成功")
#             #     else:
#             #         logger.warning("发送验证码短信[失败][ mobile: %s ]" % mobile)
#             #         return to_json_data(errno=Code.SMSFAIL, errmsg=error_map[Code.SMSFAIL])
#
#         else:# 如果表单校验失败
#             # 6.返回给前端
#             # 定义一个错误信息列表
#             err_msg_list = []
#             for item in form.errors.get_json_data().values():
#                 err_msg_list.append(item[0].get('message'))  #获取错误信息添加到列表中
#                 # print(item[0].get('message'))   # for test
#             err_msg_str = '/'.join(err_msg_list)  # 拼接错误信息为一个字符串
#
#             return to_json_data(errno=Code.PARAMERR,errmsg=err_msg_str)    # form.errors 获取表单中所有的错误信息
#
#
